#include "nvp6324.h"

/* phy clk */
static struct reg_base nvp6324_regs_base_mclk[] = {
	{0x21, 0x40, 0xff, 0x0},
	{0x21, 0x41, 0xff, 0x0},
	{0x21, 0x42, 0xff, 0x0},
	{0x21, 0x43, 0xff, 0x0},
	{0x21, 0x11, 0xff, 0x0},
	{0x21, 0x10, 0xff, 0x0},
	{0x21, 0x12, 0xff, 0x0},
	{0x21, 0x13, 0xff, 0x0},
	{0x21, 0x17, 0xff, 0x0},
	{0x21, 0x18, 0xff, 0x0},
	{0x21, 0x15, 0xff, 0x0},
	{0x21, 0x14, 0xff, 0x0},
	{0x21, 0x16, 0xff, 0x0},
	{0x21, 0x19, 0xff, 0x0},
	{0x21, 0x1a, 0xff, 0x0},
	{0x21, 0x1b, 0xff, 0x0},
	{0x21, 0x1c, 0xff, 0x0},
};

static u8 val_mclk_378[ARRAY_SIZE(nvp6324_regs_base_mclk)] = {
	0xdc,
	0x20,
	0x03,
	0x43,
	0x03,
	0x07,
	0x04,
	0x06,
	0x01,
	0x0b,
	0x02,
	0x0e,
	0x04,
	0x03,
	0x07,
	0x06,
	0x05,
};

static u8 val_mclk_594[ARRAY_SIZE(nvp6324_regs_base_mclk)] = {
	0xcc,
	0x10,
	0x03,
	0x43,
	0x04,
	0x0a,
	0x06,
	0x09,
	0x01,
	0x0d,
	0x04,
	0x16,
	0x05,
	0x05,
	0x0a,
	0x08,
	0x07,
};

static u8 val_mclk_756[ARRAY_SIZE(nvp6324_regs_base_mclk)] = {
	0xdc,
	0x10,
	0x03,
	0x43,
	0x05,
	0x0c,
	0x07,
	0x0b,
	0x01,
	0x0e,
	0x04,
	0x1c,
	0x07,
	0x06,
	0x0d,
	0x0b,
	0x09,
};

static u8 val_mclk_1242[ARRAY_SIZE(nvp6324_regs_base_mclk)] = {
	0xdc,
	0x10,
	0x03,
	0x43,
	0x08,
	0x13,
	0x0b,
	0x12,
	0x02,
	0x12,
	0x07,
	0x2d,
	0x0b,
	0x09,
	0x15,
	0x11,
	0x0e,
};

struct nvp6324_mipi_clk {
	enum nvp6324_phy_mclks mode;
	struct reg_pack reg_pack;
};

struct nvp6324_mipi_clk nvp6324_mipi_clk_data[nvp6324_mclk_max +1] = {
	{ nvp6324_378mhz,
		{ nvp6324_regs_base_mclk,
		  val_mclk_378,
		  ARRAY_SIZE(nvp6324_regs_base_mclk)
		},
	},
	{ nvp6424_594mhz,
		{ nvp6324_regs_base_mclk,
		  val_mclk_594,
		  ARRAY_SIZE(nvp6324_regs_base_mclk)
		},
	},
	{ nvp6324_756mhz,
		{ nvp6324_regs_base_mclk,
		  val_mclk_756,
		  ARRAY_SIZE(nvp6324_regs_base_mclk)
		},
	},
	{ nvp6324_1242mhz,
		{ nvp6324_regs_base_mclk,
		  val_mclk_1242,
		  ARRAY_SIZE(nvp6324_regs_base_mclk)
		},
	}
};

static struct reg_base nvp6324_regs_base_mipi_fmt[] = {
	{0x21, 0x3e, 0xff, 0x0},
	{0x21, 0x3f, 0xff, 0x0},
	{0x20, 0x01, 0xff, 0x0},
};

static u8 val_mipi_fmt_1080p25[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0x00,
};

static u8 val_mipi_fmt_720p25[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0x55,
};

static u8 val_mipi_fmt_sdp25[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0xaa,
};

static u8 val_mipi_fmt_1080p30[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0x00,
};

static u8 val_mipi_fmt_720p30[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0x55,
};

static u8 val_mipi_fmt_sdp30[ARRAY_SIZE(nvp6324_regs_base_mipi_fmt)] = {
	0x00,
	0x00,
	0xaa,
};

struct nvp6324_mipi_fmt {
	struct reg_pack reg_pack;
};

struct nvp6324_mipi_fmt nvp6324_mipi_fmt_data[nvp6324_fps_max + 1][nvp6324_mode_max + 1] = {
	/* 25 fps */
	{
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_1080p25,
			  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			},
		},
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_720p25,
		 	  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			},
		},
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_sdp25,
			  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			}
		},
	},

	/* 30 fps */
	{
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_1080p30,
			  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			},
		},
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_720p30,
			  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			},
		},
		{
			{ nvp6324_regs_base_mipi_fmt,
			  val_mipi_fmt_sdp30,
			  ARRAY_SIZE(nvp6324_regs_base_mipi_fmt),
			},
		},
	},

	{
	},

	{
	},
};

static struct reg_base nvp6324_regs_base_mipi_type[] = {
	{0x21, 0x44, 0xff, 0x0},
	{0x21, 0x49, 0xff, 0x0},
	{0x21, 0x49, 0xff, 0x0},
	{0x21, 0x44, 0xff, 0x0},
	{0x21, 0x08, 0xff, 0x0},
	{0x21, 0x0f, 0xff, 0x0}, // MIPI_TX_FRAME_CNT_EN
	{0x21, 0x38, 0xff, 0x0}, // mipi data type
	{0x21, 0x39, 0xff, 0x0},
	{0x21, 0x3a, 0xff, 0x0},
	{0x21, 0x3b, 0xff, 0x0},
	{0x21, 0x07, 0xff, 0x0},

	{0x21, 0xc8, 0xff, 0x0}, // disable parallel
	{0x21, 0xc9, 0xff, 0x0},
	{0x21, 0xca, 0xff, 0x0},
	{0x21, 0xcb, 0xff, 0x0},
	{0x21, 0xcc, 0xff, 0x0},
	{0x21, 0xcd, 0xff, 0x0},
	{0x21, 0xce, 0xff, 0x0},
	{0x21, 0xcf, 0xff, 0x0},
};

static u8 val_mipi_type_yuv422[ARRAY_SIZE(nvp6324_regs_base_mipi_type)] = {
	0x00,
	0xf3,
	0xf0,
	0x02,
	0x40,
	0x01,
	0x1e,
	0x1e,
	0x1e,
	0x1e,
	0x0f,

	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
};

#if 0
static u8 val_mipi_type_yuv420[ARRAY_SIZE(nvp6324_regs_base_mipi_type)] = {
	0x00,
	0xf3,
	0xf0,
	0x02,
	0x40,
	0x01,
	0x18,
	0x18,
	0x18,
	0x18,
	0x0f,

	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
};

static u8 val_mipi_type_yuv420_legacy[ARRAY_SIZE(nvp6324_regs_base_mipi_type)] = {
	0x00,
	0xf3,
	0xf0,
	0x02,
	0x40,
	0x01,
	0x1a,
	0x1a,
	0x1a,
	0x1a,
	0x0f,

	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
	0x00,
};
#endif

void nvp6324_mipi_init(struct nvp6324_dev *nvp6324)
{
	struct reg_pack reg_pack;

	memcpy(&reg_pack, &nvp6324_mipi_clk_data[nvp6324->phy_mclks].reg_pack, sizeof(reg_pack));

	nvp6324_transfer_regs(nvp6324, &reg_pack, 0, 1);

	reg_pack.pbase = nvp6324_regs_base_mipi_type;
	reg_pack.pval = val_mipi_type_yuv422;
	reg_pack.size = ARRAY_SIZE(nvp6324_regs_base_mipi_type);

	nvp6324_transfer_regs(nvp6324, &reg_pack, 0, 1);
}

void nvp6324_mipi_fmt_set(struct nvp6324_dev *nvp6324)
{
	enum nvp6324_fps fps = nvp6324->current_fps;
	enum nvp6324_mode mode = nvp6324_video_current_mode(nvp6324);
	struct nvp6324_mipi_fmt *fmt = &nvp6324_mipi_fmt_data[fps][mode];
	printk(KERN_ERR "lmy-log: ---%s,%d!fps index:%d, mode index:%d---\n", __FUNCTION__,__LINE__, fps, mode);

	nvp6324_transfer_regs(nvp6324, &fmt->reg_pack, 0, 1);
}

static struct reg_base nvp6324_regs_base_arb[] = {
	{0x20, 0x00, 0xff, 0x0},
	{0x20, 0x40, 0xff, 0x0},
	{0x20, 0x0f, 0xff, 0x0},
	{0x20, 0x0d, 0xff, 0x0},
	{0x20, 0x40, 0xff, 0x0},
	{0x20, 0x00, 0xff, 0x0},
};

static u8 val_arb_yuv422[ARRAY_SIZE(nvp6324_regs_base_arb)] = {
	0x00,
	0x01,
	0x00,
	0x01,
	0x00,
	//0xff,//four channel
	0x11,//single channel
};

#if 0
static u8 val_arb_yuv420[ARRAY_SIZE(nvp6324_regs_base_arb)] = {
	0x00,
	0x01,
	0xaa,
	0x01,
	0x00,
	0xff,
};
static u8 val_arb_yuv420_legacy[ARRAY_SIZE(nvp6324_regs_base_arb)] = {
	0x00,
	0x01,
	0x55,
	0x01,
	0x00,
	0xff,
};
#endif

void nvp6324_arb_init(struct nvp6324_dev *nvp6324)
{
	struct reg_pack reg_pack;

	reg_pack.pbase = nvp6324_regs_base_arb;
	reg_pack.pval = val_arb_yuv422;
	reg_pack.size = ARRAY_SIZE(nvp6324_regs_base_arb);

	nvp6324_transfer_regs(nvp6324, &reg_pack, 0, 1);
}
